package com.jhws.core.shiro.realms;

import java.util.List;

import javax.annotation.Resource;

import com.jhws.common.base.bo.Global;
import com.jhws.core.shiro.execption.secLevelAccountEmptyException;
import com.jhws.sys.role.service.ITblRolemenuDimService;
import com.jhws.sys.user.service.UserCommsService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import com.jhws.sys.role.bo.TblRoleDimBo;
import com.jhws.sys.user.bo.TblUserDimBo;
import com.jhws.sys.role.service.ITblRoleDimService;
import com.jhws.sys.user.service.ITblUserDimService;
import com.jhws.util.LogHelper;


public class UserRealm extends AuthorizingRealm {


    @Resource
    ITblUserDimService userService;
    @Resource
    UserCommsService userCommsService;
    @Resource
    ITblRoleDimService IRoleService;
    @Resource
    ITblRolemenuDimService IRoleMenuService;

    /*
        当前认证源只支持用户密码类型
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        LogHelper.getLogger().debug("token -- " + token.getClass().getSimpleName());
        if ("UsernamePasswordToken".equals(token.getClass().getSimpleName()))
            return true;
        return false;
    }

    /*
         *  @create time : 2016-9-30 下午5:08:50
         *  @author : Alex Tan
         *  @comments :获取该用户所属角色的权限列表，用于匹配用户所申请的权限
         */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        List<TblUserDimBo> list = userService.findTblUserDimByWhere("where log_name = '" + username + "'");
        if (list == null || list.size() == 0)
            return authorizationInfo;
        TblRoleDimBo role = IRoleService.findTblRoleDimById(list.get(0).getRoleCode());
        authorizationInfo.addRole(role.getRoleName());
        /* 从该角色的所有祖先中,判断是否有符合条件的角色 */
        String parents = role.getRoleParents();
        if (StringUtils.isNotEmpty(parents)) {
            String[] parentItem = parents.split(",");
            for (String parent : parentItem)
                authorizationInfo.addRole(parent);
        }

        /* 权限表缓存一份在session中 */
        List<String> perms = (List)SecurityUtils.getSubject().getSession().getAttribute("perms");
        if(perms == null) {
            /* 权限可能存在角色中也可能独属于用户 */
            perms = IRoleMenuService.getPermsByRole(role.getRoleCode());
            List<String> userPerms = userService.findUserPerms(list.get(0).getUserCode());
            if(perms != null) {
                perms.addAll(userPerms);
                SecurityUtils.getSubject().getSession().setAttribute("perms", perms);
            }
        }
        authorizationInfo.addStringPermissions(perms);

        return authorizationInfo;
    }

    /* 
     *  @create time : 2016-9-30 下午5:09:33
     *  @author : Alex Tan
     *  @comments :用户身份认证，获取该用户的用户名与密码进行对比
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {


        String username = (String) token.getPrincipal();
        LogHelper.getLogger().debug("");
        TblUserDimBo user = null;

        try {
            user = userService.getUserByName(username);

            if (user == null) {
                throw new UnknownAccountException();//没找到帐号
            }

            /*if (IRoleService.isRole(user.getRoleName(), Global.ROLE_SEC_LEVEL_ADMIN)) {
                if (userCommsService.getCommCountByName(user.getLogName()) == 0)
                    throw new secLevelAccountEmptyException();
            }*/

        } catch (AuthenticationException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getLogName(), //用户名
                user.getLogPwd(), //密码
                ByteSource.Util.bytes("hehe"),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

}
